package com.study;

import com.study.Person;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 反射：将类各个组成部分封装为其他对象，反射机制
 * 好处：
 * 1、在程序运行过程中操作对象
 * 2、解耦，提高可扩展性
 *
 * Field:成员变量
 * 操作：
 * 1、设置值 void set(Object obj, Object value)
 * 2、获取值 get(Object obj)
 *
 * Constructor:构造方法
 * 创建对象
 */
public class ReflectDemo {
    public static void main(String[] args) {
        try{
//            test1();
//            test2();
            test3();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void test3() throws Exception{
        // 0.获取Person的Class对象
        Class personClass = Person.class;

        // 获取指定名称的方法
        Method m = personClass.getMethod("eat");
        Person p = new Person("周星驰", 100);
        m.invoke(p); // 执行方法

        // 获取指定名称的带参方法
        Method m1 = personClass.getMethod("eat", String.class);
        m1.invoke(p,"水果"); // 执行方法

        System.out.println("===========");

        // 获取所有public修饰的方法,包含父类
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
            System.out.println(method.getName());
        }

        // 获取类名
        String className = personClass.getName();
        System.out.println(className);
    }

    public static void test2() throws Exception{
        // 0.获取Person的Class对象
        Class personClass = Person.class;

        //
        Constructor constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);
        // 创建对象
        Object person = constructor.newInstance("张三", 23);
        System.out.println(person);

        // 空参构造对象
//        Object o = personClass.newInstance();
//        System.out.println(o);
    }

    public static void test1() throws Exception{
        // 0.获取Person的Class对象
        Class personClass = Person.class;

        // 1.Field[] getFields() 获取public成员变量
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        System.out.println("---------------------");
        Field a = personClass.getField("name");

        // 2、获取public成员变量name的值
        Person p = new Person("周星驰", 55);
        Object value = a.get(p);
        System.out.println(value);

        // 设置
        a.set(p, "谭孝海");
        System.out.println(p);
        System.out.println("---------------------");

        // Field[] getDeclaredFields() 获取所有成员变量，不考虑修饰符
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }

        // 获取
        Field d = personClass.getDeclaredField("d");
        d.setAccessible(true); // 设置访问私有成员权限
        Object value2 = d.get(p);
        System.out.println(value);
    }
}
